package hotciv.framework;

/** Game is a Facade pattern that encapsulate all access and manipulation
   of a HotCiv game.

  Responsibilities:
  1) Return the 'world' as an iteration over its tiles.
  
<#if type == "code">

<#include "/data/author.txt">
</#if>
*/

public interface Game {
  /** the size of the world is set permanently to a 16x16 grid */
  public static final int WORLDSIZE = 16;
  
  // === Accessor methods ===================================
  
  /** return a specific tile.
   * PreCondition: Position p is a valid position in the world.
   * @param p the position in the world that must be returned.
   * @return the tile at position p.
   */
  public Tile getTile( Position p );

  /** return the uppermost unit in the stack of units at position 'p'
   * in the world
   * PreCondition: Position p is a valid position in the world.
   * @param p the position in the world.
   * @return the unit that is at the top of the unit stack at position
   * p, OR null if no units are present at position p.
   */
  public Unit getUnitAt( Position p );
  
  /** return the city at position 'p' in the world
   * PreCondition: Position p is a valid position in the world.
   * @param p the position in the world.
   * @return the city at this position or null if no city here.
   */
  public City getCityAt( Position p );

  /** return the player that is 'in turn', that is, is able to
   * move units and manage cities.
   * @return the player that is in turn
   */
  public Player getPlayerInTurn();
    
  // === Mutator methods ======================================
  /** move a unit from one position to another
   * PreCondition: both from and to are within the limits of the
   * world.
   * PreCondition: there is a unit located at position from.
   * @param from the position that the unit has now
   * @param to the position the unit should move to
   * @return true if the move is valid (no mountain etc.), and
   * false otherwise. If false is returned, the unit stays in
   * the same position and its "move" is intact (it can be moved to 
   * another position.)
   */
  public boolean moveUnit( Position from, Position to );
  
  /** do end-of-turn processing which entails 
   * A) restore unit's move counts
   * B) produce food and material in cities
   * C) potentially produce units in cities
   * D) make the turn go over to next player
   */
  public void endOfTurn();
  
  /** change the work force's focus in a city, i.e. what
   * kind of production there will be emphasis on in the city.
   * PreCondition there is a city at location 'p'.
   * @param p the position of the city whose focus 
   * should be changed. 
   * @param balance a string defining the focus of the work
   * force in a city. Valid values are at least 
   * GameConstants.productionFocus and 
   * GameConstants.foodFocus.
   */
  public void changeWorkForceFocusInCityAt( Position p, String balance );
  
  /** change the type of unit a city will produce next. 
   * PreCondition there is a city at location 'p'.
   * @param p the position of the city whose production
   * should be changed. 
   * @param unitType a string defining the type of unit that the
   * city should produce next.
   */
  public void changeProductionInCityAt( Position p, String unitType );
  
  // === Observer behavior ====================================
  /** add an observer to this game.
   * @param observer the observer to add.
   */
  public void addGameObserver( GameObserver observer );
}
